package generic.net;

import generic.net.Response.Status;

/**
 * A PendingResponse is the response to a request, that may or may not have
 * arrived.
 *
 * @author Adam Scarr <scarr.adam@gmail.com>
 */
public class PendingResponse {
    private Thread sleepingThread = null;
    private Request request;
    private Response response = null;
    private long timeout = 10000;

    /**
     * Creates a new PendingRequest.
     * @param request           The request
     * @param sleepingThread    The thread that is waiting for a response.
     */
    public PendingResponse(Request request) {
        this.request = request;
    }

    /**
     * @return The request made.
     */
    public Request getRequest() {
        return request;
    }

    /**
     * Start sleeping waiting for a response. The RequestManager should wake us
     * up when one arrives, but just in case we will bail and assume the
     * conenction is dead after 10 seconds.
     * @return  The response.
     */
    public synchronized Response getResponse() {
        sleepingThread = Thread.currentThread();

        // We start blocking here, Just fall asleep, the RequestManager should
        // tap us one the shoulder when the bus gets here...
        try {
            Thread.sleep(10000);
        } catch (InterruptedException ex) {
            return response;
        }

        System.out.println("[Pending Response] Gave up waiting for response #" + request.getID() + " (" + request.getServiceProvider() + ":" + request.getRequestType() + ")" );
        Response r = new Response(request);
        r.setStatus(Status.NO_REPLY);
        return r;

    }

    /**
     * Starts sleeping waiting for a response. The RequestManager should wake
     * us up when one arrives, or when we reach the timeout.
     * @param timeout   Time in milliseconds to wait for a response.
     * @return          The response, or null if timeout has elapsed.
     */
    public synchronized Response getResponse(long timeout) {
        sleepingThread = Thread.currentThread();

        if (response == null) {
            // We fall asleep waiting for the bus again, but this time we remember
            // to set an alarm, just-in-case...
            try {
                Thread.sleep(timeout);
            } catch (InterruptedException ex) {}
        }

        return response;
    }

    /**
     * Let the sleeping thread know that a response has arrived and pass it on.
     * @param response
     */
    public void setResponse(Response response) {
        this.response = response;
        if (sleepingThread != null) sleepingThread.interrupt();
    }
}
